package cn.flant.io.tools;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import cn.flant.exec.ExecuteThread;
import cn.flant.io.IOUtil;

public class TcpConnector extends Connector {
	private Socket socket = null;
	private boolean isConnected = false;
	private InputStream in = null;
	private OutputStream out = null;
	private InputMonitor monitor = new InputMonitor();

	public TcpConnector(String host, int port) {
		super(host, port);
	}

	public TcpConnector(String host, int port, boolean enableCache) {
		super(host, port, enableCache);
	}

	@Override
	protected void closeConnection() {
		isConnected = false;
		if (socket != null) {
			IOUtil.close(socket);
			socket = null;
		}
		if (out != null) {
			IOUtil.close(out);
			out = null;
		}
		if (in != null) {
			IOUtil.close(in);
			in = null;
		}
		monitor.shutdown();
	}

	@Override
	protected boolean openConnection() {
		if (isConnected) {
			return true;
		}
		try {
			socket = new Socket(host, port);
			in = socket.getInputStream();
			out = socket.getOutputStream();
			isConnected = true;
			monitor.startup();
			return true;
		} catch (Exception e) {
			log.error("can not connect to host: [" + host + ":" + port + "], cause: " + e.getMessage());
			closeConnection();
		}
		return false;
	}

	@Override
	public boolean isConnected() {
		return isConnected;
	}

	@Override
	protected boolean sendData(byte[] bytes) {
		try {
			out.write(bytes);
			out.flush();
			return true;
		} catch (Exception e) {
			closeConnection();
		}
		return false;
	}

	private class InputMonitor extends ExecuteThread {
		public void run() {
			try {
				while (isRunning() && in.read() != -1) {
				}
			} catch (Exception e) {
			} finally {
				isConnected = false;
				closeConnection();
				shutdown();
			}
		}
	}
}
